// ...........................................................................................................
// (C) Copyright  1996/2008 Fuego Inc.  All Rights Reserved
// THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Fuego Inc.
// The copyright notice above does not evidence any actual or intended
// publication of such source code.
//
// Last changed on 2008-01-31 14:19:06 (-0300), by: pcolunga. $Revision$
// ...........................................................................................................

package com.webcamtracker.tracker.example.spatial;

import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.webcamtracker.move.tracking.TrackingEvent;
import com.webcamtracker.move.tracking.TrackingEventListener;
import com.webcamtracker.move.tracking.TrackingEventType;

import javax.media.j3d.Background;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.*;
import javax.vecmath.Vector3f;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;

public class SpatialPanel
        extends JPanel {
    //~ Instance fields ......................................................................................

    private Spatial spatial;

    //~ Constructors .........................................................................................

    public SpatialPanel() {
        setLayout(new BorderLayout());
        setPreferredSize(new Dimension(Spatial.PORTAL_WIDTH, Spatial.PORTAL_HEIGHT));
        init();
        TrackingPanel.buildTrackingFrame((TrackingEventListener) spatial);
    }

    //~ Methods ..............................................................................................

    public Spatial getSpatial() {
        return spatial;
    }

    private void init() {
        GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();

        Canvas3D canvas3D = new Canvas3D(config);
        add(canvas3D, BorderLayout.CENTER);

        BranchGroup scene = branch();

        SimpleUniverse simpleUniverse = new SimpleUniverse(canvas3D);

        // This will move the ViewPlatform back a bit so the
        // objects in the scene can be viewed.
        simpleUniverse.getViewingPlatform().setNominalViewingTransform();

        simpleUniverse.addBranchGraph(scene);
    }

    private BranchGroup branch() {
        BranchGroup scene = new BranchGroup();

        TransformGroup space = setInitialCamara();

        this.spatial = new Spatial(space, 320, 240);

        space.addChild(this.spatial);

        scene.addChild(space);

        camaraRotate(space, scene);

        addBackGround(scene);

        scene.compile();

        return scene;
    }

    private TransformGroup setInitialCamara() {
        TransformGroup tg = new TransformGroup();
        tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        tg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);

        Transform3D transform = new Transform3D();
        Vector3f vector = new Vector3f(.0F, .0F, -4.0F);
        transform.setTranslation(vector);

        tg.setTransform(transform);

        return tg;
    }

    private void camaraRotate(TransformGroup tg, BranchGroup scene) {
        MouseRotate myMouseRotate = new MouseRotate();
        myMouseRotate.setTransformGroup(tg);
        myMouseRotate.setSchedulingBounds(new BoundingSphere());
        scene.addChild(myMouseRotate);
    }

    private void addBackGround(BranchGroup scene) {
        Background background = new Background();
        background.setColor(.0F, .0F, .0F);
        background.setApplicationBounds(new BoundingSphere());
        scene.addChild(background);
    }



    public static class TrackingPanel
            extends JPanel
    {
        private Point point = new Point(160, 120);
        private Point lastPoint = new Point(160, 120);
        private int pointSize = 15;

        private final Dimension preferredSize = new Dimension(320, 240);

        private TrackingPanel(final TrackingEventListener listener, final String id)
        {
            setPreferredSize(preferredSize);
            initListeners(listener, id);
        }

        private void initListeners(final TrackingEventListener listener, final String id)
        {
            addMouseMotionListener(new MouseMotionAdapter() {
                public void mouseDragged(MouseEvent e) {
                    lastPoint = point;
                    point = e.getPoint();
                     float realZoom = (float) pointSize / 15;
                    if (point.x < 0) point.x = 0;
                    if (point.x > preferredSize.getWidth()) point.x = (int) preferredSize.getWidth();
                    if (point.y < 0) point.y = 0;
                    if (point.y > preferredSize.getHeight()) point.y = (int) preferredSize.getHeight();

                    listener.trackingEventDispatched(
                            new TrackingEvent(null, point, null, TrackingEventType.TRACKING_CHANGED,id,realZoom));
                    repaint();
                }
            });

            addMouseWheelListener(new MouseWheelListener() {
                public void mouseWheelMoved(MouseWheelEvent e) {
                    int zoom = e.getWheelRotation();

                    pointSize += pointSize < 100 ? pointSize > 7 ? zoom : zoom > 0 ? zoom : 0 : zoom < 0 ? zoom : 0;

                    float realZoom = (float) pointSize / 15;

                    listener.trackingEventDispatched(
                            new TrackingEvent(null, point, new Point((int) realZoom * 1000, (int) realZoom * 100), TrackingEventType.TRACKING_CHANGED,id,realZoom));

                    repaint();
                }
            });
        }


        public void paint(Graphics g) {
            g.clearRect(this.lastPoint.x - this.pointSize * 2,
                    this.lastPoint.y - pointSize * 2,
                    this.pointSize * 4,
                    this.pointSize * 4);

            g.setColor(Color.RED);

            g.fillOval(this.point.x - this.pointSize, this.point.y - this.pointSize,
                    this.pointSize * 2, this.pointSize * 2);

            g.setColor(Color.WHITE);

            ((Graphics2D) g).setStroke(new BasicStroke(1.5F));

            g.drawRoundRect((int) (preferredSize.getWidth() / 2) - 8,
                    (int) (preferredSize.getHeight() / 2) - 8, 16, 16, 4, 4);
        }

        public static void buildTrackingFrame(TrackingEventListener listener)
        {
            buildTrackingFrame(listener, "mouse");
        }

        public static void buildTrackingFrame(TrackingEventListener listener, String id)
        {
            JFrame frame = new JFrame("Tracking Pad");
            frame.setContentPane(new TrackingPanel(listener, id));
            frame.pack();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setResizable(false);
            frame.setVisible(true);
        }
    }

}
